﻿using ImportExporter.ImportAttributes;
using Playnite.SDK;
using Playnite.SDK.Data;
using Playnite.SDK.Events;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace ImportExporter
{
    public class ImportExporter : GenericPlugin
    {
        private static readonly ILogger logger = LogManager.GetLogger();

        private ImportExporterSettingsViewModel settings { get; set; }

        private const string metadateFilePath = "E:/PlayniteMetadata/";
        private const string imageFilesPath = "E:/Playnite1033/library/files/";
        public override Guid Id { get; } = Guid.Parse("eb750ca6-abf5-45fc-92fe-5ffdf0b0758c");

        public ImportExporter(IPlayniteAPI api) : base(api)
        {
            settings = new ImportExporterSettingsViewModel(this);
            Properties = new GenericPluginProperties
            {
                HasSettings = true
            };
        }

        public void DoUpdate(string directoryPath, List<string> attributeNameList)
        {
            // Update仅能更新3个文本字段，Name，Description和Notes
            string[] files = Directory.GetFiles(Path.Combine(directoryPath, "games"), "*.*", SearchOption.AllDirectories);
            List<string> jsonFiles = new List<string>();
            foreach (string file in files)
            {
                if (Path.GetExtension(file).Equals(".json", StringComparison.OrdinalIgnoreCase))
                {
                    jsonFiles.Add(file);
                }
            }
            var progressOptions = new GlobalProgressOptions(String.Empty, true)
            {
                IsIndeterminate = false
            };
            _ = PlayniteApi.Dialogs.ActivateGlobalProgress((progressAction) =>
            {
                progressAction.ProgressMaxValue = jsonFiles.Count;
                int index = 0;

                foreach (string file in jsonFiles)
                {
                    index++;
                    progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} {file}";
                    progressAction.CurrentProgressValue = index;
                    if (progressAction.CancelToken.IsCancellationRequested)
                    {
                        break;
                    }
                    try
                    {
                        Game tempGame = Serialization.FromJsonFile<Game>(file);
                        Game game = PlayniteApi.Database.Games.Where<Game>(g => g.Id == tempGame.Id).FirstOrDefault<Game>();
                        if (attributeNameList.Contains("Name"))
                        { 
                            game.Name = tempGame.Name;
                        }
                        if (attributeNameList.Contains("Description"))
                        { 
                            game.Description = tempGame.Description;
                        }
                        if (attributeNameList.Contains("Notes"))
                        { 
                            game.Notes = tempGame.Notes;
                        }

                        PlayniteApi.Database.Games.Update(game);
                        Utils.CopyDirectory(Path.Combine(directoryPath, "games", $@"{game.Id}"), Path.Combine(imageFilesPath, $@"{game.Id}"));
                    }
                    catch (Exception ex)
                    {
                        PlayniteApi.Notifications.Add(new NotificationMessage("UpdateError", ex.Message, NotificationType.Error));
                        continue;
                    }
                }
            }, progressOptions);

            //Game game = Serialization.FromJsonFile<Game>("E:/PlayniteMetadata/be0d9352-bacd-496f-ba46-b0bb23ce4a8c.json");
            //PlayniteApi.Database.Games.Add(game);
            PlayniteApi.Dialogs.ShowMessage($"已完成游戏{jsonFiles.Count}元数据的更新!", "ImportExporter");
        }
        
        public void DoPublish(List<Game> gameslist, string directoryPath)
        {
            var progressOptions = new GlobalProgressOptions(String.Empty, true)
            {
                IsIndeterminate = false
            };
            _ = PlayniteApi.Dialogs.ActivateGlobalProgress((progressAction) =>
            {
                progressAction.ProgressMaxValue = gameslist.Count;
                int index = 0;
                foreach (Game game in gameslist)
                {
                    index++;
                    progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} {game.Name}";
                    progressAction.CurrentProgressValue = index;
                    if (progressAction.CancelToken.IsCancellationRequested)
                    {
                        break;
                    }

                    FakeGame fGame = new FakeGame(game);
                    try
                    {
                        Utils.WriteJsonFile(Path.Combine(directoryPath, "publish", $@"{game.Id}.json"), fGame);
                        //Utils.CopyDirectory(Path.Combine(imageFilesPath, $@"{game.Id}"), Path.Combine(directoryPath, "games", $@"{game.Id}"));
                    }
                    catch (IOException ex)
                    {
                        PlayniteApi.Notifications.Add(new NotificationMessage("PublishError", ex.Message, NotificationType.Error));
                        continue;
                    }
                }

                
                PlayniteApi.Dialogs.ShowMessage($"已完成游戏{gameslist.Count}数据的发布!", "ImportExporter");
            }, progressOptions);
        }

        public void DoExport(List<Game> gameslist, string directoryPath)
        {
            var progressOptions = new GlobalProgressOptions(String.Empty, true)
            {
                IsIndeterminate = false
            };
            _ = PlayniteApi.Dialogs.ActivateGlobalProgress((progressAction) =>
            {
                progressAction.ProgressMaxValue = gameslist.Count + 14;
                int index = 0;
                foreach (Game game in gameslist)
                {
                    index++;
                    progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} {game.Name}";
                    progressAction.CurrentProgressValue = index;
                    if (progressAction.CancelToken.IsCancellationRequested)
                    {
                        break;
                    }

                    try
                    {
                        Utils.WriteJsonFile(Path.Combine(directoryPath, "games", $@"{game.Id}.json"), game);
                        Utils.CopyDirectory(Path.Combine(imageFilesPath, $@"{game.Id}"), Path.Combine(directoryPath, "games", $@"{game.Id}"));
                    }
                    catch (IOException ex)
                    {
                        PlayniteApi.Notifications.Add(new NotificationMessage("ExportError", ex.Message, NotificationType.Error));
                        continue;
                    }
                }

                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export ageratings";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "ageratings", $@"ageratings.json"), PlayniteApi.Database.AgeRatings);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export companies";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "companies", $@"companies.json"), PlayniteApi.Database.Companies);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export completionstatuses";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "completionstatuses", $@"completionstatuses.json"), PlayniteApi.Database.CompletionStatuses);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export emulators";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "emulators", $@"emulators.json"), PlayniteApi.Database.Emulators);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export features";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "features", $@"features.json"), PlayniteApi.Database.Features);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export filterpresets";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "filterpresets", $@"filterpresets.json"), PlayniteApi.Database.FilterPresets);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export genres";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "genres", $@"genres.json"), PlayniteApi.Database.Genres);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export importexclusions";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "importexclusions", $@"importexclusions.json"), PlayniteApi.Database.ImportExclusions);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export platforms";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "platforms", $@"platforms.json"), PlayniteApi.Database.Platforms);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export regions";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "regions", $@"regions.json"), PlayniteApi.Database.Regions);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export scanners";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "scanners", $@"scanners.json"), PlayniteApi.Database.GameScanners);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export series";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "series", $@"series.json"), PlayniteApi.Database.Series);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export sources";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "sources", $@"sources.json"), PlayniteApi.Database.Sources);
                index++;
                progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} export tags";
                progressAction.CurrentProgressValue = index;
                Utils.WriteJsonFile(Path.Combine(directoryPath, "tags", $@"tags.json"), PlayniteApi.Database.Tags);
                //Utils.WriteJsonFile(Path.Combine("E:/PlayniteMetadata/tools", $@"tools.json"), PlayniteApi.Database.);
                //foreach (Platform platform in PlayniteApi.Database.Platforms)
                //{
                //    Utils.WriteJsonFile(Path.Combine("E:/PlayniteMetadata/platforms", $@"{game.Id}.json"), game);
                //}
                PlayniteApi.Dialogs.ShowMessage($"已完成游戏{gameslist.Count}元数据的导出!", "ImportExporter");
            }, progressOptions);
        }

        public void DoImport(string directoryPath)
        {
            //Game origin = gameslist[0];
            string[] files = Directory.GetFiles(Path.Combine(directoryPath, "games"), "*.*", SearchOption.AllDirectories);
            List<string> jsonFiles = new List<string>();
            foreach (string file in files)
            {
                if (Path.GetExtension(file).Equals(".json", StringComparison.OrdinalIgnoreCase))
                {
                    jsonFiles.Add(file);
                }
            }
            var progressOptions = new GlobalProgressOptions(String.Empty, true)
            {
                IsIndeterminate = false
            };
            _ = PlayniteApi.Dialogs.ActivateGlobalProgress((progressAction) =>
            {
                progressAction.ProgressMaxValue = jsonFiles.Count + 14;
                int index = 0;
                List<AgeRating> importedAgeRatingList = Serialization.FromJsonFile<List<AgeRating>>(Path.Combine(directoryPath, "ageratings", $@"ageratings.json"));
                List<Company> importedCompanyList = Serialization.FromJsonFile<List<Company>>(Path.Combine(directoryPath, "companies", $@"companies.json"));
                List<CompletionStatus> importedCompletionStatusList = Serialization.FromJsonFile<List<CompletionStatus>>(Path.Combine(directoryPath, "completionstatuses", $@"completionstatuses.json"));
                List<GameFeature> importedFeatureList = Serialization.FromJsonFile<List<GameFeature>>(Path.Combine(directoryPath, "features", $@"features.json"));
                List<Genre> importedGenreList = Serialization.FromJsonFile<List<Genre>>(Path.Combine(directoryPath, "genres", $@"genres.json"));
                List<Platform> importedPlatformList = Serialization.FromJsonFile<List<Platform>>(Path.Combine(directoryPath, "platforms", $@"platforms.json"));
                List<Region> importedRegionList = Serialization.FromJsonFile<List<Region>>(Path.Combine(directoryPath, "regions", $@"regions.json"));
                List<Series> importedSeriesList = Serialization.FromJsonFile<List<Series>>(Path.Combine(directoryPath, "series", $@"series.json"));
                List<GameSource> importedSourceList = Serialization.FromJsonFile<List<GameSource>>(Path.Combine(directoryPath, "sources", $@"sources.json"));
                List<Tag> importedTagList = Serialization.FromJsonFile<List<Tag>>(Path.Combine(directoryPath, "tags", $@"tags.json"));

                foreach (string file in jsonFiles)
                {
                    index++;
                    progressAction.Text = $"{index}/{progressAction.ProgressMaxValue} {file}";
                    progressAction.CurrentProgressValue = index;
                    if (progressAction.CancelToken.IsCancellationRequested)
                    {
                        break;
                    }
                    try
                    {
                        Game game = Serialization.FromJsonFile<Game>(file);
                        ImportAgeRatings.DoImportAgeRatings(this.PlayniteApi, game, importedAgeRatingList);
                        ImportPublishers.DoImportPublishers(this.PlayniteApi, game, importedCompanyList);
                        ImportDevelopers.DoImportDevelopers(this.PlayniteApi, game, importedCompanyList);
                        ImportCompletionStatuses.DoImportCompletionStatuses(this.PlayniteApi, game, importedCompletionStatusList);
                        ImportFeatures.DoImportFeatures(this.PlayniteApi, game, importedFeatureList);
                        ImportGenres.DoImportGenres(this.PlayniteApi, game, importedGenreList);
                        ImportPlatforms.DoImportPlatforms(this.PlayniteApi, game, importedPlatformList);
                        ImportRegions.DoImportRegions(this.PlayniteApi, game, importedRegionList);
                        ImportSeries.DoImportSeries(this.PlayniteApi, game, importedSeriesList);
                        ImportSources.DoImportSources(this.PlayniteApi, game, importedSourceList);
                        ImportTags.DoImportTags(this.PlayniteApi, game, importedTagList);

                        PlayniteApi.Database.Games.Add(game);
                        Utils.CopyDirectory(Path.Combine(directoryPath, "games", $@"{game.Id}"), Path.Combine(imageFilesPath, $@"{game.Id}"));
                    }
                    catch (Exception ex)
                    {
                        PlayniteApi.Notifications.Add(new NotificationMessage("ImportError", ex.Message, NotificationType.Error));
                        continue;
                    }
                }
            }, progressOptions);

            //Game game = Serialization.FromJsonFile<Game>("E:/PlayniteMetadata/be0d9352-bacd-496f-ba46-b0bb23ce4a8c.json");
            //PlayniteApi.Database.Games.Add(game);
            PlayniteApi.Dialogs.ShowMessage($"已完成游戏{jsonFiles.Count}元数据的导入!", "ImportExporter");
        }

        
        public override void OnGameInstalled(OnGameInstalledEventArgs args)
        {
            // Add code to be executed when game is finished installing.
        }

        public override void OnGameStarted(OnGameStartedEventArgs args)
        {
            // Add code to be executed when game is started running.
        }

        public override void OnGameStarting(OnGameStartingEventArgs args)
        {
            // Add code to be executed when game is preparing to be started.
        }

        public override void OnGameStopped(OnGameStoppedEventArgs args)
        {
            // Add code to be executed when game is preparing to be started.
        }

        public override void OnGameUninstalled(OnGameUninstalledEventArgs args)
        {
            // Add code to be executed when game is uninstalled.
        }

        public override void OnApplicationStarted(OnApplicationStartedEventArgs args)
        {
            // Add code to be executed when Playnite is initialized.
        }

        public override void OnApplicationStopped(OnApplicationStoppedEventArgs args)
        {
            // Add code to be executed when Playnite is shutting down.
        }

        public override void OnLibraryUpdated(OnLibraryUpdatedEventArgs args)
        {
            // Add code to be executed when library is updated.
        }

        public override ISettings GetSettings(bool firstRunSettings)
        {
            return settings;
        }

        public override UserControl GetSettingsView(bool firstRunSettings)
        {
            return new ImportExporterSettingsView();
        }

        public override IEnumerable<MainMenuItem> GetMainMenuItems(GetMainMenuItemsArgs args)
        {
            List<MainMenuItem> mainMenuItems = new List<MainMenuItem>
            {
                new MainMenuItem
                {
                    MenuSection = "@批量导入导出",
                    //Icon = Path.Combine(pluginFolder, "icon.png"),
                    Description = "导出",
                    Action = (MainMenuItem) =>
                    {
                        DoExport(PlayniteApi.MainView.FilteredGames.ToList(), metadateFilePath);
                        //cleanup = false;
                        //DoDispatchHtml(PlayniteApi.MainView.FilteredGames.ToList());
                    }
                },
                new MainMenuItem
                {
                    MenuSection = "@批量导入导出",
                    //Icon = Path.Combine(pluginFolder, "icon.png"),
                    Description = "导入",
                    Action = (MainMenuItem) =>
                    {
                        DoImport(metadateFilePath);
                        //cleanup = false;
                        //DoDispatchHtml(PlayniteApi.Database.Games.ToList());
                    }
                },
                new MainMenuItem
                {
                    MenuSection = "@批量导入导出",
                    //Icon = Path.Combine(pluginFolder, "icon.png"),
                    Description = "发布",
                    Action = (MainMenuItem) =>
                    {
                        DoPublish(PlayniteApi.MainView.FilteredGames.ToList(), metadateFilePath);
                        //cleanup = false;
                        //DoDispatchHtml(PlayniteApi.MainView.FilteredGames.ToList());
                    }
                },
                new MainMenuItem
                {
                    MenuSection = "@批量导入导出",
                    //Icon = Path.Combine(pluginFolder, "icon.png"),
                    Description = "更新(名称)",
                    Action = (MainMenuItem) =>
                    {
                        DoUpdate(metadateFilePath, new List<string> { "Name" });
                        //cleanup = false;
                        //DoDispatchHtml(PlayniteApi.Database.Games.ToList());
                    }
                },
                new MainMenuItem
                {
                    MenuSection = "@批量导入导出",
                    //Icon = Path.Combine(pluginFolder, "icon.png"),
                    Description = "更新(描述)",
                    Action = (MainMenuItem) =>
                    {
                        DoUpdate(metadateFilePath, new List<string> { "Description" });
                        //cleanup = false;
                        //DoDispatchHtml(PlayniteApi.Database.Games.ToList());
                    }
                },
            };
            return mainMenuItems;
        }
    }
}